package cn.yhbk.web.modules.manager.Service.Impl;

import cn.hutool.core.bean.BeanUtil;
import cn.yhbk.web.common.Util.MyUtil;
import cn.yhbk.web.common.api.CommonPage;
import cn.yhbk.web.common.exception.ApiException;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaCheck.GpaCheckConditionDTO;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaCheck.Words;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaDetails.AddDetails;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaDetails.DetailsCalculateDTO;
import cn.yhbk.web.modules.manager.Pojo.DTO.GpaDetails.DetailsResP;
import cn.yhbk.web.modules.manager.Pojo.Entity.TbGpaCheck;
import cn.yhbk.web.modules.manager.Mapper.TbGpaCheckMapper;
import cn.yhbk.web.modules.manager.Pojo.Entity.TbGpaRecord;
import cn.yhbk.web.modules.manager.Pojo.Entity.TbItems;
import cn.yhbk.web.modules.manager.Pojo.Entity.TbStudent;
import cn.yhbk.web.modules.manager.Pojo.VO.GpaCheck.CheckOperateDetail;
import cn.yhbk.web.modules.manager.Pojo.VO.GpaCheck.GpaCheckAdd;
import cn.yhbk.web.modules.manager.Pojo.VO.GpaCheck.GpaCheckResP;
import cn.yhbk.web.modules.manager.Service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 有何不可
 * @since 2023-08-20
 */
@Service
@Slf4j
public class TbGpaCheckServiceImpl extends ServiceImpl<TbGpaCheckMapper, TbGpaCheck> implements ITbGpaCheckService {

    @Autowired
    ITbStudentService studentService;

    @Autowired
    IGpaCheckDetailsService detailsService;

    @Autowired
    ITbGpaFlowPathService flowPathService;

    @Autowired
    TbGpaCheckMapper checkMapper;

    @Autowired
    ITbGpaRecordService recordService;

    @Autowired
    EmailService emailService;


    @Autowired
    ITbItemsLevelaService itemsLevelaService;

    @Autowired
    ITbItemsService itemsService;


    @Override
    @Transactional
    public boolean addCheck(GpaCheckAdd add) {
        Long adminId = MyUtil.getCurrentAdminId();
        Long studentId = studentService.getStudentIdByAdminId(adminId);

        //判断当年有没有过申请
        LambdaQueryWrapper<TbGpaCheck> lambda = new QueryWrapper<TbGpaCheck>().lambda();

        lambda.eq(TbGpaCheck::getYear,String.valueOf(LocalDate.now().getYear()));
        lambda.eq(TbGpaCheck::getStuId,studentId);
        List<TbGpaCheck> tmpList = list(lambda);
        if(!tmpList.isEmpty())throw new ApiException("请勿重复申请");

        TbGpaRecord record = recordService.getRecordByStudentId(studentId);



        TbGpaCheck check = new TbGpaCheck();
        BeanUtil.copyProperties(add, check);
        check.setScoreGpa(record.getScoreGpa());
        check.setPass((byte) (record.getPass() ? 1 : 0));
        //DetailsCalculateDTO calculateRes = calculate(check.getScoreGpa(), add);

        //设置年份
        LocalDate now = LocalDate.now();
        String year = String.valueOf(now.getYear());
        check.setYear(year);

        //设置学生id
        check.setStuId(studentId);
        boolean save = save(check);

        if (!save) {
            log.error("保存失败!");
            throw new ApiException("添加失败!请联系管理员");
        }

        //保存详细信息
        boolean success = detailsService.addDetails(add.getDetails(), check.getId());

        if (!success) {
            log.error("details保存失败!");
            throw new ApiException("添加失败!请联系管理员");
        }

        return true;
    }

    private DetailsCalculateDTO calculate(Long checkId) {

        List<DetailsResP> detailsByCheckIds = detailsService.getDetailsByCheckIds(Collections.singletonList(checkId));
        TbGpaCheck check = getById(checkId);

        DetailsCalculateDTO res = new DetailsCalculateDTO();

        //附件集合
        List<String> resource = new ArrayList<>();
        //总绩点
        double gpaSum;
        //综测分数
        double gpaQuality = 0;

        for (DetailsResP detailsByCheckId : detailsByCheckIds) {
            gpaQuality += detailsByCheckId.getGpaNum();
        }

        gpaSum = check.getScoreGpa() + gpaQuality;

        //设置综测分数
        res.setGpaQuality(gpaQuality);

        //设置总分数
        res.setGpaSum(gpaSum);

        return res;
    }


    @Override
    public CommonPage<GpaCheckResP> getCheck(Long currentPage, Long pageSize, GpaCheckConditionDTO conditionDTO) {
        Page<TbGpaCheck> page = new Page<>(currentPage, pageSize);

        QueryWrapper<TbGpaCheck> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<TbGpaCheck> lambda = wrapper.lambda();

        Long id = conditionDTO.getId();
        lambda.eq(!Objects.isNull(id), TbGpaCheck::getId, id);

        List<Integer> status = conditionDTO.getStatus();
        if (!Objects.isNull(status) && !status.isEmpty()) {
            lambda.in(TbGpaCheck::getStatus, status);
        }

        Double scoreGpa = conditionDTO.getScoreGpa();
        lambda.eq(!Objects.isNull(scoreGpa), TbGpaCheck::getScoreGpa, scoreGpa);

        String year = conditionDTO.getYear();
        lambda.eq(!Strings.isBlank(year), TbGpaCheck::getYear, year);

        Byte pass = conditionDTO.getPass();
        lambda.eq(!Objects.isNull(pass), TbGpaCheck::getPass, pass);

        Double gpaSum = conditionDTO.getGpaSum();
        lambda.eq(!Objects.isNull(gpaSum), TbGpaCheck::getGpaSum, gpaSum);

        Double gpaQuality = conditionDTO.getGpaQuality();
        lambda.eq(!Objects.isNull(gpaQuality), TbGpaCheck::getGpaQuality, gpaQuality);

        String refuse = conditionDTO.getRefuse();
        lambda.like(!Strings.isBlank(refuse), TbGpaCheck::getRefuse, refuse);

        List<Long> stuIds = conditionDTO.getStuIds();
        if (!Objects.isNull(stuIds)) {
            if (stuIds.isEmpty()) stuIds.add(-1L);
            lambda.in(TbGpaCheck::getStuId, stuIds);
        }


        Boolean finish_check = conditionDTO.getFinish_check();
        lambda.eq(!Objects.isNull(finish_check), TbGpaCheck::getFinishCheck, finish_check);


        Page<TbGpaCheck> dataPage = page(page, lambda);

        List<GpaCheckResP> resList = packData(dataPage.getRecords());

        CommonPage<GpaCheckResP> resPage = CommonPage.restPage(dataPage, new CommonPage<GpaCheckResP>());
        resPage.setList(resList);
        return resPage;
    }

    @Override
    public boolean judgeCheckStatus(Long checkId) {
        //拿到当前申请记录的status
        TbGpaCheck check = getById(checkId);
        Integer status = check.getStatus();

        //拿到当前角色的order
        Integer order = flowPathService.getCurrentFlow();
        return status.equals(order);
    }

    @Override
    @Transactional
    public boolean consent(Long checkId) {
        //修改状态
        TbGpaCheck check = getById(checkId);
        Integer status = check.getStatus() + 1;
        check.setStatus(status);

        //计算所有绩点综合

        DetailsCalculateDTO calculate = calculate(checkId);
        check.setGpaSum(calculate.getGpaSum());
        check.setGpaQuality(calculate.getGpaQuality());

        //判断是否完成审核，是则修改完成审核标识
        boolean pass = isPass(status);
        if (pass) {
            check.setFinishCheck(true);
        }

        boolean update = updateById(check);
        if (!update) {
            log.error("修改状态异常!");
            return false;
        }

        //修改绩点记录表

        boolean updateRecord = recordService.updateGpa(check.getStuId(), calculate.getGpaSum(), calculate.getGpaQuality());
        if (!updateRecord) {
            log.error("绩点记录更新失败!");
            throw new ApiException("更新失败!");
        }

        // 发送邮件
        if (pass) {
            // 发送邮件
            QueryWrapper<TbStudent> studentQueryWrapper = new QueryWrapper<>();
            studentQueryWrapper.select("email, job_number", "name").eq("id", check.getStuId());
            TbStudent one = studentService.getOne(studentQueryWrapper);
            if (one.getEmail() != null){
                emailService.sendNoticeSuccess(one.getEmail(), one.getJobNumber().toString(), one.getName());
            }
        }

        return true;
    }

    @Override
    @Transactional
    public boolean turnDown(Long checkId, List<CheckOperateDetail> details) {
        for (CheckOperateDetail detail : details) {
            checkMapper.refuseUpdate(detail.getDetailId(), detail.getRefuseReason());
        }

        // 发送邮件
        TbGpaCheck check = getById(checkId);
        QueryWrapper<TbStudent> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.select("email, job_number", "name").eq("id", check.getStuId());
        TbStudent one = studentService.getOne(studentQueryWrapper);
        if(one.getEmail() != null){
            emailService.sendNoticeFail(one.getEmail(), one.getJobNumber().toString(), one.getName());
        }

        return true;
    }

    @Override
    public boolean judgeCheckStu(Long checkId) {

        Long adminId = MyUtil.getCurrentAdminId();
        Long stuId = studentService.getStudentIdByAdminId(adminId);

        QueryWrapper<TbGpaCheck> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<TbGpaCheck> lambda = wrapper.lambda();

        lambda.eq(TbGpaCheck::getId, checkId);
        lambda.eq(TbGpaCheck::getStuId, stuId);
        TbGpaCheck one = getOne(lambda);

        return !Objects.isNull(one);
    }

    @Override
    public boolean delCheck(Long checkId) {

        //删除详情
        boolean success = detailsService.delDetailByCheckId(checkId);
        if (!success) return false;

        //删除申请记录
        return removeById(checkId);
    }

    @Override
    public boolean haveChecking() {
        TbGpaCheck check = checkMapper.haveChecking();
        return !Objects.isNull(check);
    }

    @Override
    public List<Long> getCheckIdsByStuId(Long stuId) {
        if (Objects.isNull(stuId)) return new ArrayList<>();
        QueryWrapper<TbGpaCheck> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<TbGpaCheck> lambda = wrapper.lambda();

        lambda.eq(TbGpaCheck::getStuId, stuId);
        List<TbGpaCheck> list = list(lambda);
        return list.stream().map(TbGpaCheck::getId).collect(Collectors.toList());

    }

    @Override
    public GpaCheckAdd getGpgByImg(List<Words> wordsList) {
        System.out.println(wordsList.get(0).getResult());
        GpaCheckAdd res = new GpaCheckAdd();
        Map<Long, List<AddDetails>> details = new HashMap<>();

        List<String> activityKey = itemsService.getActivityKey();
        for (Words item : wordsList) {
            //拿到活动名称
            String activityName = "";
            Double gpaNum = 0D;
            List<String> resourceList = new ArrayList<>();


            String grade = "国家级";
            String level = "";

            Pattern compile = Pattern.compile("\\b.*[比|大|竞]赛.*\\b");
            Pattern levelCompile = Pattern.compile("\\b.*[秀胜等]奖\\b");
            Pattern gradeCompileSchool = Pattern.compile("\\b.*[大学|学院]\\b");
            Pattern gradeCompile = Pattern.compile("\\b.*省.*\\b");
            for (int i = 0; i < item.getResult().size(); i++) {
                String word = item.getResult().get(i);
                Matcher matcher = compile.matcher(word);
                Matcher matcher1 = levelCompile.matcher(word);

                if (matcher1.find()) {
                    level = word;
                }
                if (matcher.find()) {
                    for (String key : activityKey) {
                        String regex = "\\b.*" + key + ".*\\b";
                        boolean pattern = Pattern.compile(regex).matcher(word).find();
                        System.out.println(word);
                        if (pattern) {
                            activityName = key;
                            break;
                        }
                    }
                    Matcher gradeMatcher = gradeCompileSchool.matcher(word);

                    Matcher gradeMatcher1 = gradeCompile.matcher(word);


                    if (gradeMatcher.find()) {
                        grade = "校级";
                    } else if (gradeMatcher1.find()) {
                        grade = "省级";
                    }


                }


            }

            Matcher matcher = gradeCompileSchool.matcher(activityName);

            //根据活动名称拿到绩点值
            //判断活动是否存在
            TbItems tbItems = itemsService.checkActivity(activityName);
            if (!Objects.isNull(tbItems)) {
                gpaNum = itemsLevelaService.getGpaNum(grade, level);
            }

            resourceList.add(item.getImg_path());
            AddDetails addDetails = new AddDetails();
            addDetails.setGpaNum(gpaNum);
            addDetails.setActivityName(tbItems.getContestName());
            addDetails.setResource(resourceList);

            List<AddDetails> tmp = details.get(1L);
            if (Objects.isNull(tmp)) {
                tmp = new ArrayList<>();
            }
            tmp.add(addDetails);
            details.put(1L, tmp);
            System.out.println(level + " " + grade);
        }
        res.setDetails(details);

        System.out.println(details);
        return res;
    }

    private boolean isPass(Integer status) {
        Integer lastOrder = flowPathService.getLastOrder();
        return status.equals(lastOrder + 1);
    }

    private List<GpaCheckResP> packData(List<TbGpaCheck> records) {
        if (records.isEmpty()) return new ArrayList<>();

        List<Long> checkIds = records.stream().map(TbGpaCheck::getId).distinct().collect(Collectors.toList());

        //拿到所有学生
        List<Long> studentIds = records.stream().map(TbGpaCheck::getStuId).distinct().collect(Collectors.toList());
        if (studentIds.isEmpty()) studentIds.add(-1L);
        List<TbStudent> studentList = studentService.listByIds(studentIds);
        Map<Long, TbStudent> studentMap = studentList.stream().collect(Collectors.toMap(TbStudent::getId, item -> item));


        //拿到所有详情
        List<DetailsResP> details = detailsService.getDetailsByCheckIds(checkIds);

        Map<Long, List<DetailsResP>> detailsMap = details.stream().collect(Collectors.groupingBy(DetailsResP::getCheckId));

        List<GpaCheckResP> resPList = records.stream().map(item -> {
            GpaCheckResP tmpRes = new GpaCheckResP();
            BeanUtil.copyProperties(item, tmpRes);

            //设置学生
            TbStudent student = studentMap.get(item.getStuId());
            tmpRes.setStudent(student);

            //处理详情
            List<DetailsResP> detailsListTmp = detailsMap.get(item.getId());
            Map<Long, List<DetailsResP>> mapTmp = detailsListTmp.stream().collect(Collectors.groupingBy(DetailsResP::getCategoryId));

            tmpRes.setDetails(mapTmp);

            return tmpRes;
        }).collect(Collectors.toList());

        return resPList;
    }
}
